package data;

import utils.HTMLParser;
import utils.MiException;
import ClasesPrincipales.Pelicula;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;


import utils.Tupla;

/**
 *  * @author fikipollo
 * Esta clase se usará para descargar la información de la página cinetube.es. En concreto
 * se descargará la información de las películas.
 *
 * La estrcutura de la cinetube.es se peude resumir así:
 *  · Todas las películas se enceuntran en el apartado de películas con URL www.cinetube.es/peliculas/
 *  · Las películas se encuentran organizadas por orden alfabético, habiendo una o más páginas para cada
 *      letra. Ej. películas que empiezan por A --> www.cinetube.es/peliculas/A, www.cinetube.es/peliculas/A/2.html, www.cinetube.es/peliculas/A/3.html,...
 *      hasta un máximo (comprobado de una en una) de 9 páginas.
 *  · Cada película tiene su página ej. http://www.cinetube.es/peliculas/drama/ver-pelicula-a-20-millas-de-la-justicia.html
 *  · Cada película tiene 0 o más
 *          links para online -->   http://www.cinetube.es/peliculas/drama/a-20-millas-de-la-justicia_espanol-dvd-rip-megavideo-223694.html
 *          links para descarga --> http://www.cinetube.es/peliculas/drama/descargar-a-20-millas-de-la-justicia_espanol-dvd-rip-megaupload-223695.html
 *  · Cada uno de los links para online o descarga tienen a su vez uno o más links a los servidores (megavideo, megaupload, fileserver...)
 */

public class ExtractorPeliculasCinetube {

    ArrayList<Pelicula> peliculas;
    /**
     * Funcion que descarga las peliculas que empiezen con la letra dada como parametro
     * @param letraAux 
     */
    public void extractListaPeliculas(String letra) {
        String rootPath = "http://www.cinetube.es/peliculas/";
        String pageContent;
        
        try {
            peliculas =  new ArrayList<Pelicula>();
            //Descargamos el codigo HTML de la primera pagina del indice de peliculas que empizan por letra
            pageContent = HTMLParser.downloadURL(rootPath + letra + "/");
            //Eliminamos el codigo no relevante
            pageContent = removeIrrelevantCode(pageContent, "<div id=" + '"' + "pelis_online" + '"' + ">", "</div><div style=" + '"' + "clear:both;" + '"' + "></div>", "</div>");
            //Extraemos los links a la pagina de cada una de las peliculas y extraemos su informacion
            extractInfoPeliculas(HTMLParser.extractLinks(pageContent));
            
            //Se repite el proceso para cada una de las paginas del indice de peliculas
            //A diferencia de las primera página, a partir de la segunda la direccion cambia
            for (int nPage = 2; nPage < 10; nPage++) {
                pageContent = HTMLParser.downloadURL(rootPath + letra + "/" + nPage + ".html");
                pageContent = removeIrrelevantCode(pageContent, "<div id=" + '"' + "pelis_online" + '"' + ">", "</div><div style=" + '"' + "clear:both;" + '"' + "></div>", "</div>");
                extractInfoPeliculas(HTMLParser.extractLinks(pageContent));
            }

            guardarPeliculasFichero(letra);



        } catch (MiException ex) {
            Logger.getLogger(ExtractorPeliculasCinetube.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Extrae la informacion de cada una de las paginas de peliculas dadas en el array
     * @param letra
     * @param linksPeliculas
     */
    public void extractInfoPeliculas(ArrayList<Tupla> linksPeliculas) {
        String link;
        for (int i = 0; i < linksPeliculas.size(); i = i + 2) {
            link = linksPeliculas.get(i).getElem2().toString();
            //Solo los links que llevan a peliculas contienen la cadena "ver-pelicula"
            if (link.contains("ver-pelicula")) {
                System.out.println("Extrayendo pelicula: " + link);
                //Para la pelicula dada, se extrae su info (descripcion, genero y los links online y de descarga)
                Pelicula pelicula = extractInfoPelicula(link);
                if (pelicula != null) {
//                    guardarPeliculaFichero(pelicula);
                    peliculas.add(pelicula);
                }
                // Retardo de un 2 segundos (2000 milisegundos) para no saturar el servidor
                try {
                    System.out.println("ESPERANDO 2 SEGUNDOS");
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }

    /**
     * Extrae la informacion de la pelicula dada por su URL 
     * @param urlPelicula
     * @return objeto tipo Pelicula
     */
    private Pelicula extractInfoPelicula(String urlPelicula) {
        try {
            String url = "http://www.cinetube.es" + urlPelicula;
            //Descargamos el contenido HTML
            String pageContent = HTMLParser.downloadURL(url);
            //Extrae del HTML la descripcion de la pelicula y sus keywords
            String[] infoPelicula = HTMLParser.extractDescripcionAndKeywords(pageContent);
            //Elimina el codigo HTML inutil
            pageContent = removeIrrelevantCode(pageContent, "<div id=" + '"' + "ficha_ver_peli" + '"' + ">", "<div class=" + '"' + "publi_ft" + '"' + " style=" + '"' + "position:relative;" + '"' + ">", "");
            //Extrae todos los links de la pelicula y crea una Pelicula con toda la informacion
            return new Pelicula(infoPelicula[0], infoPelicula[1], infoPelicula[2], infoPelicula[3], extractLinksPelicula(HTMLParser.extractLinks(pageContent)));
        } catch (Exception ex) {
            Logger.getLogger(ExtractorPeliculasCinetube.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    /**
     * Extrae los links de la pelicula dada, dividiendolos en 2 tipos: links para ver online y links de descarga
     * @param linksPeliculas
     * @return ArrayList con links
     */
    private ArrayList<String> extractLinksPelicula(ArrayList<Tupla> linksPeliculas) {
        String link;
        ArrayList<String> links = new ArrayList<String>();
        //Para cada link encontrado en la pagina
        for (Tupla tupla : linksPeliculas) {
            link = tupla.getElem2().toString();
            System.out.println("\tExtrayendo link: " + link);
            String url = "http://www.cinetube.es" + link;
            try {
                //Descargamos el codigo HTML de la pagina a la q nos lleva el link
                String pageContent = HTMLParser.downloadURL(url);
                //Si el link  contiene la palabra descargar, sera una url de un servidor de descarga
                if (link.contains("descargar")) {
                    //Eliminamos el codigo HTML inutil
                    pageContent = removeIrrelevantCode(pageContent, "<textarea", "</textarea>", "");
                    //Se extrae una lista de uno o más links para descargar
                    String[] downloadLinks = HTMLParser.extractDownloadLinks(pageContent);
                    for (int i = 1; i < downloadLinks.length - 1; i++) {
                        System.out.println("\t\tLink Descarga: " + downloadLinks[i]);
                        links.add("\t\tDescarga: " + downloadLinks[i]);
                    }
                } else {
                    //Si el link era para ver ONLINE
                    pageContent = removeIrrelevantCode(pageContent, "<span>URL del Video:</span>", "</div>", "");
                    String onlineLink = HTMLParser.extractOnlineLink(pageContent);
                    System.out.println("\t\tLink Online: " + onlineLink);
                    links.add("\t\tOnline: " + onlineLink);
                }
            } catch (Exception ex) {
                Logger.getLogger(ExtractorPeliculasCinetube.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return links;
    }

    /**
     * Elimina el codigo HTML innecesario dejando sólo el codigo que se desea, acotado por objetive1 y objetive2. Si es necesario
     * inserta al final del codigo devuelto la cadena finalText
     * @param htmlCode
     * @param objetive1
     * @param objetive2
     * @param finalText
     * @return codigo HTML relevante
     */
    private String removeIrrelevantCode(String htmlCode, String objetive1, String objetive2, String finalText) {
        String relevant = htmlCode.split(objetive1)[1];
        relevant = relevant.split(objetive2)[0];
        relevant += finalText;
        return relevant;
    }

    /**
     * Guarda una pelicula en su correspondiente fichero. En la primera version se guarda
     * un fichero por cada pelicula.
     * @param letra
     * @param pelicula
     */
    private void guardarPeliculasFichero(String letra) {
        FileWriter fichero = null;
        PrintWriter pw = null;

        try {
            fichero = new FileWriter("./Data/Peliculas/" + letra + ".dat");
            pw = new PrintWriter(fichero);
            for(Pelicula pelicula : peliculas)
                pw.write(pelicula.toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // Nuevamente aprovechamos el finally para
                // asegurarnos que se cierra el fichero.
                if (null != fichero) {
                    fichero.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }

    /**
     * Función principal que recibe una letra inicial y otra final (probablemente elegidas
     * por el usuario) y que descarga las películas que comienzen por las letras comprendidas
     * en el intervalo
     * @param letraIni
     * @param letraFin
     */
    public void extract(String letraIni, String letraFin) {
        char letraInicial = letraIni.charAt(0);
        char letraFinal = letraFin.charAt(0);

        ExtractorPeliculasCinetube ex = new ExtractorPeliculasCinetube();
        if (letraIni.equalsIgnoreCase("0-9")) {
            java.io.File dir = new File("./Data/Peliculas/");
            dir.mkdirs();

            ex.extractListaPeliculas("0-9");
            try {
                System.out.println("ESPERANDO 5 SEGUNDOS");
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            letraInicial = 'A';
        }

        for (char letra = letraInicial; letra <= letraFinal; letra++) {
            java.io.File dir = new File("./Data/Peliculas/");
            dir.mkdirs();

            ex.extractListaPeliculas("" + letra);
            try {
                System.out.println("ESPERANDO 5 SEGUNDOS");
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
